package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.bean.sysmenu.SysMenuDO;
import com.example.demo.bean.sysrolemenu.SysRoleMenuDO;
import com.example.demo.bean.sysuser.SysUserDO;
import com.example.demo.bean.sysuser.SysUserRoleDO;
import com.example.demo.context.SysContext;
import com.example.demo.dto.sysmenu.TreeRoleMenuRep;
import com.example.demo.dto.sysmenu.TreeSysMenuRep;
import com.example.demo.exception.OtherException;
import com.example.demo.mapper.sysmenu.SysMenuMapper;
import com.example.demo.mapper.sysuser.SysUserMapper;
import com.example.demo.service.ISysMenuService;
import com.example.demo.service.ISysRoleMenuService;
import com.example.demo.service.ISysUserRoleService;
import com.example.demo.util.SysUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuDO> implements ISysMenuService {

    @Resource
    private SysMenuMapper sysMenuMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private ISysUserRoleService sysUserRoleService;
    @Resource
    private ISysRoleMenuService sysRoleMenuService;

    /**
     * 获取树形菜单
     *
     * @return
     */
    @Override
    public List<TreeSysMenuRep> getTreeSysMenu() {
        List<SysMenuDO> sysMenuDOS = new ArrayList<>();
        Long currUserId = Long.parseLong(SysContext.get());
        // 校验用户是否可用
        validUserAvailable(currUserId);
        // 获取用户信息
        SysUserDO sysUserDO = sysUserMapper.selectById(currUserId);

        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 0);
        queryWrapper.ne("menu_type", "F");
        // 处理超级管理员用户
        if (sysUserDO.getIsRoot() == 1) {
            sysMenuDOS = sysMenuMapper.selectList(queryWrapper);
        } else {
            // 获取角色信息
            SysUserRoleDO userRole = sysUserRoleService.getSysUserRole(currUserId);
            // 获取角色菜单信息
            SysRoleMenuDO sysRoleMenu = sysRoleMenuService.getSysRoleMenuByRoleId(new SysRoleMenuDO().setRoleId(userRole.getRoleId()));
            queryWrapper.in("menu_id", Arrays.asList(sysRoleMenu.getMenuIds().split(",")));
            sysMenuDOS = sysMenuMapper.selectList(queryWrapper);
        }
        return SysUtil.GENERATE_ROUTER(sysMenuDOS);
    }

    /**
     * 获取菜单列表
     *
     * @return
     */
    @Override
    public List<TreeSysMenuRep> getSysMenuListWithoutAction() {
        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("menu_type", "F");
        List<SysMenuDO> sysMenuDOS = sysMenuMapper.selectList(queryWrapper);
        return SysUtil.GENERATE_ROUTER(sysMenuDOS);
    }

    /**
     * 获取菜单列表--全部
     */
    @Override
    public List<TreeRoleMenuRep> getSysMenuAllList() {
        List<SysMenuDO> sysMenuDOS = sysMenuMapper.selectList(null);
        return SysUtil.GENERATE_ROLE_MENU_TREE(sysMenuDOS);
    }

    /**
     * 添加菜单
     *
     * @param sysMenuDO 菜单项
     * @return
     */
    @Override
    public int addSysMenu(SysMenuDO sysMenuDO) {
        if (sysMenuDO.getPath() != "") {
            validMenuPathExist(sysMenuDO.getPath(), null);
        }
        return sysMenuMapper.insert(sysMenuDO);
    }

    /**
     * 删除菜单
     *
     * @param sysMenuDO
     * @return
     */
    @Override
    public int deleteSysMenu(SysMenuDO sysMenuDO) {
        validExist(sysMenuDO.getMenuId());
        validChildExist(sysMenuDO.getMenuId());
        return sysMenuMapper.deleteById(sysMenuDO.getMenuId(), false);
    }

    /**
     * 更新菜单
     *
     * @param sysMenuDO
     * @return
     */
    @Override
    public int updateSysMenu(SysMenuDO sysMenuDO) {
        validExist(sysMenuDO.getMenuId());
        if (!"F".equals(sysMenuDO.getMenuType()) && !sysMenuDO.getPath().isEmpty()) {
            validMenuPathExist(sysMenuDO.getPath(), sysMenuMapper.selectById(sysMenuDO.getMenuId()));
        }
        return sysMenuMapper.updateById(sysMenuDO);
    }

    /**
     * 查询菜单
     *
     * @param sysMenuDO
     * @return
     */
    @Override
    public SysMenuDO getSysMenu(SysMenuDO sysMenuDO) {
        validExist(sysMenuDO.getMenuId());
        return sysMenuMapper.selectById(sysMenuDO.getMenuId());
    }

    /**
     * 查询菜单所有子按钮
     *
     * @param sysMenuDO
     */
    @Override
    public List<SysMenuDO> getAllActionByMenuId(SysMenuDO sysMenuDO) {
        validExist(sysMenuDO.getMenuId());
        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", sysMenuDO.getMenuId());
        queryWrapper.eq("status", 0);
        queryWrapper.eq("menu_type", "F");
        return sysMenuMapper.selectList(queryWrapper);
    }


    /**
     * 根据id获取用户权限
     *
     * @param userId
     * @return
     */
    @Override
    public List<String> getUserPermissions(Long userId) {
        ArrayList<String> permsList = new ArrayList<>();
        validUserAvailable(userId);
        SysUserDO info = sysUserMapper.selectById(userId);

        // 处理超管权限
        if (info.getIsRoot() == 1) {
            permsList.add("*");
        } else {
            QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("status", 0);
            queryWrapper.eq("menu_type", "F");
            // 获取角色信息
            SysUserRoleDO userRole = sysUserRoleService.getSysUserRole(userId);
            // 获取角色菜单信息
            SysRoleMenuDO sysRoleMenu = sysRoleMenuService.getSysRoleMenuByRoleId(new SysRoleMenuDO().setRoleId(userRole.getRoleId()));
            queryWrapper.in("menu_id", Arrays.asList(sysRoleMenu.getMenuIds().split(",")));
            // 根据当前用户分配的角色查询
            List<SysMenuDO> permissionsList = sysMenuMapper.selectList(queryWrapper);
            permissionsList.forEach(item -> {
                permsList.add(item.getPerms());
            });
        }
        return permsList;
    }

    /**
     * 校验菜单是否存在
     *
     * @param menuId
     */
    private void validExist(Long menuId) {
        if (Objects.isNull(sysMenuMapper.selectById(menuId))) {
            throw new OtherException("菜单不存在");
        }
    }

    private void validChildExist(Long parentId) {
        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId);
        if (!sysMenuMapper.selectList(queryWrapper).isEmpty()) {
            throw new OtherException("存在子菜单禁止删除");
        }
    }

    /**
     * 校验菜单路径是否存在
     *
     * @param newPath
     * @param sysMenuDO
     */
    private void validMenuPathExist(String newPath, SysMenuDO sysMenuDO) {
        QueryWrapper<SysMenuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("path", newPath);
        SysMenuDO exist = sysMenuMapper.selectOne(queryWrapper);
        if (exist != null) {
            if (sysMenuDO != null) {
                if (!Objects.equals(exist.getMenuId(), sysMenuDO.getMenuId())) {
                    throw new OtherException("路由地址已存在");
                }
            } else {
                throw new OtherException("路由地址已存在");
            }
        }
    }

    private void validUserAvailable(Long userId) {
        SysUserDO exist = sysUserMapper.selectById(userId);
        if (exist == null) {
            throw new OtherException("用户不存在");
        } else {
            if (exist.getStatus() == 1) {
                throw new OtherException("用户已禁用");
            }
        }
    }
}
